<template>
  <VueDraggable
    v-model="list"
    :animation="150"
    handle=".drag_handle"
    ghost-class="ghost"
    class="exp_list_group"
    group="g1">
    <div v-for="(item, idx) in modelValue" :key="item.id" class="exp_drag" :style="{ width: getExpItemWidth(item) }">
      <div class="exp_line">
        <div class="expression">
          <!-- 拖动手柄 -->
          <i class="el-icon-s-fold drag_handle"></i>
          <span :style="{ color: getExpItemColor(item) }">{{ item.name }}</span>
        </div>
        <i class="el-icon-close exp_close" @click.stop="removeItem(item, idx)"></i>
      </div>
      <!-- 递归渲染子表达式 (在 flex wrap 布局中，括号单独成行, 换行 div 的宽度要和外部容器的宽度保持一致) -->
      <div v-if="item.type == ExpresionType.Parentheses" style="width: 800px"></div>
      <nested-component
        v-if="item.type == ExpresionType.Parentheses"
        :model-value.sync="item.children"
        class="nested_exp"></nested-component>
      <div v-if="item.type == ExpresionType.Parentheses" style="width: 800px"></div>
    </div>
  </VueDraggable>
</template>

<script>
// 引入自定义组件
import { ExpresionType } from './expression';
// 引入第三方组件
import { VueDraggable } from 'vue-draggable-plus';

export default {
  name: 'NestedComponent',
  components: {
    VueDraggable,
  },
  props: {
    modelValue: {
      type: Array,
      required: true,
    },
  },
  data() {
    return {
      list: this.modelValue,
      ExpresionType: ExpresionType,
    };
  },
  watch: {
    modelValue: {
      handler(newValue) {
        this.list = newValue;
      },
      deep: true,
    },
    list: {
      handler(newValue) {
        this.$emit('update:modelValue', newValue);
      },
      deep: true,
    },
  },
  methods: {
    getExpItemColor(item) {
      if (item.type == ExpresionType.Parentheses) {
        return '#F56C6C';
      }
      switch (item.name) {
        case '与':
          return '#409eff';
        case '或':
          return '#67c23a';
        case '非':
          return '#e6a23c';
        default:
          return '#97a8be';
      }
    },
    getExpItemWidth(item) {
      if (item.type == ExpresionType.Parentheses) {
        return 'auto'; // 由于是递归嵌套 不能设置为固定宽度
      }
      if (item.type == ExpresionType.ImmediateValue) {
        return 'auto'; // 自适应标签文字长度
      }
      if (['与', '或', '非'].includes(item.name)) {
        return '80px'; // 逻辑操作符，固定长度
      }
      return '200px';
    },
    removeItem(item, idx) {
      if (item.type != ExpresionType.Parentheses) {
        this.list.splice(idx, 1);
        return;
      }
      this.$confirm('这会删除整个括号, 确定删除吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => {
          this.list.splice(idx, 1);
        })
        .catch(() => {});
    },
  },
};
</script>

<style lang="scss" scoped>
.ghost {
  opacity: 0.5;
  background-color: #c8cffb;
}
/* 递归使用的类，不能嵌套在其他类中 */
.exp_list_group {
  width: auto;
  min-width: 300px;
  min-height: 40px;
  background: #f0f0f0;
  padding: 10px;
  margin: 5px 0;
  border-radius: 4px;
  display: flex;
  flex-wrap: wrap;
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
}

.exp_drag {
  padding: 8px;
  margin: 4px 0;
  background: white;
  border: 1px solid #ddd;
  border-radius: 4px;

  .exp_line {
    display: flex;
    align-items: center;
    justify-content: space-between;

    .expression {
      display: inline-flex;
      align-items: center;
      justify-content: flex-start;
      gap: 8px;

      .drag_handle {
        cursor: move;
        display: inline-block;
        user-select: none;
      }
    }

    .exp_close {
      cursor: pointer;
      margin-left: 8px;
    }
  }
}

.nested_exp {
  margin-left: 20px;
  margin-top: 8px;
}
</style>
